<template>
  <view v-if="tempFilePath" class="card">
    <view class="title">已录制</view>
    <view class="app-between">
      <view class="app-between player" @click="playBtn">
        <image
          class="icon-play"
          :src="playStatus === 0 ? '/static/icon/icon-play.png' : '/static/icon/icon-stop.png'"
        >
        </image>
        <image class="icon-sound" src="/static/icon/icon-sound.png"></image>
        <text class="time">{{ getVoiceDuration }}</text>
      </view>
      <u-icon name="trash" color="#cccccc" size="42rpx" @click="delBtn"></u-icon>
    </view>
  </view>

  <view v-if="longPress == 2" class="prompt-layer">
    <view class="prompt-popup">
      <view class="p">{{ '剩余：' + count + 's' }}</view>
      <view style="font-size: 42rpx; margin-top: 30rpx">松手 完成</view>
    </view>
  </view>

  <button class="sbmit-btn" type="default" @longpress="longpressBtn" @touchend="touchendBtn">
    <text class="inner"></text>
  </button>
</template>

<script lang="ts" setup>
import { ref, reactive, computed, nextTick } from 'vue'
import { onLoad } from '@dcloudio/uni-app'

const recordAuth = ref(false) // 是否授权录音

// 录音
const recorderManager = uni.getRecorderManager() // 录音管理对象
let init: any = null // 录制时长计时器
let timer: any = null // 播放 录制倒计时
const count = ref(0) // 录制倒计时
const longPress = ref(1) // 1显示 按住说话 2显示 说话中
// 音频
const innerAudioContext = uni.createInnerAudioContext() // audio 上下文对象
const time = ref(0) //录音时长
const duration = ref(60000) //录音最大值ms 60000/1分钟
const tempFilePath: any = ref('') //音频路径
const playStatus = ref(0) //录音播放状态 0:未播放 1:正在播放
const voiceAllTime = ref(0) //记录音频原始总时长

function recordingTimer(_time: any) {
  if (_time == undefined) {
    // 将计时器赋值给init
    init = setInterval(() => {
      time.value++
    }, 1000)
  } else {
    clearInterval(init)
  }
}

// 录音授权
function authorRecord() {
  uni.authorize({
    scope: 'scope.record', //这里选择scope.(录音、位置、用户信息...都可以)
    success() {
      // 允许授权
      console.log('已授权')
      recordAuth.value = true
    },
    fail() {
      // 拒绝授权
      uni.showModal({
        content: '检测到您没打开录音功能权限，是否去设置打开？',
        confirmText: '确认',
        confirmColor: '#1874f5',
        cancelText: '取消',
        success: (res) => {
          if (res.confirm) {
            uni.openSetting({
              // opensetting 是调起设置页面的
              success: (res) => {
                // 获取设置授权的状态
                const setting = res.authSetting
                recordAuth.value = setting['scope.record'] || false
              },
            })
          } else {
            return false
          }
        },
      })
      return false
    },
  })
}

// 长按录音事件
function longpressBtn() {
  // if(!recordAuth.value) {
  //   authorRecord()
  //   return;
  // }
  longPress.value = 2
  clearInterval(init) // 清除定时器
  countdown(60) // 倒计时
  recorderManager.onStop((res) => {
    tempFilePath.value = res.tempFilePath
    recordingTimer(time.value)
  })
  const options = {
    duration: duration.value, // 指定录音的时长，单位 ms
    sampleRate: 16000, // 采样率
    numberOfChannels: 1, // 录音通道数
    encodeBitRate: 96000, // 编码码率
    format: 'mp3', // 音频格式，有效值 aac/mp3
    frameSize: 10, // 指定帧大小，单位 KB
  }
  recordingTimer(undefined)
  recorderManager.start(options)
  // 监听音频开始事件
  recorderManager.onStart((res) => {
    console.log(res)
  })
}

// 长按松开录音事件
function touchendBtn() {
  if (!recordAuth.value) {
    return
  }

  longPress.value = 1
  recorderManager.onStop((result) => {
    console.log(result)
    // 录音结束，可以先调用删除接口将旧录音删除，然后再上传最新的录音
    // 通过 uni.uploadFile 上传录音文件，filePath 传 voice.tempFilePath，指定要上传文件资源路径
    // 下面是示例，模拟上传成功之后的处理
    // tempFilePath.value = "https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3";
    tempFilePath.value = result.tempFilePath
    innerAudioContext.src = result.tempFilePath
    // innerAudioContext.src = "https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3";
    time.value = (result.duration / 1000).toFixed(1)
    voiceAllTime.value = result.duration
  })
  recordingTimer(time.value)
  clearInterval(timer)
  recorderManager.stop()
}

// 显示音频剩余秒数
const getVoiceDuration = computed(() => {
  let _t = String(time.value)
  let str = _t.length > 1 ? `00:${_t}` : `00:0${_t}`
  return str
})

// 播放
function updateTime(val: number) {
  time.value = Number(val)
  timer = setInterval(() => {
    if (time.value >= 1) {
      time.value--
    } else {
      time.value = voiceAllTime.value
      clearInterval(timer)
    }
  }, 1000)
}
function playBtn() {
  //点击播放
  if (playStatus.value == 0) {
    playStatus.value = 1
    innerAudioContext.play()
    updateTime(time.value) // 倒计时
  } else {
    playStatus.value = 0
    innerAudioContext.pause()
    clearInterval(timer)
  }
  //播放结束
  innerAudioContext.onEnded(() => {
    playStatus.value = 0
  })
}

// 删除录音
function delBtn() {
  // 调用接口删除
  // 下面是示例，删除后的重置
  time.value = 0
  tempFilePath.value = ''
  playStatus.value = 0
  time.value = voiceAllTime.value = 0
}

// 倒计时
function countdown(val: any) {
  count.value = Number(val)
  timer = setInterval(() => {
    if (count.value > 0) {
      count.value--
    } else {
      longPress.value = 1
      clearInterval(timer)
    }
  }, 1000)
}

// 获取录音权限状态
function getRecordSetting() {
  uni.getSetting({
    success(res) {
      const setting = res.authSetting
      recordAuth.value = setting['scope.record'] || false
    },
  })
}

// 设置录音
function setVoice() {
  // 进入页面时调用接口获取上传的路由文件路径
  // 下面是示例
  tempFilePath.value = 'https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3'
  innerAudioContext.src = tempFilePath.value
  time.value = 30
  voiceAllTime.value = time.value
}

onLoad(() => {
  nextTick(() => {
    setVoice()

    getRecordSetting()
  })
})
</script>

<style lang="scss" scoped>
.card {
  margin: 0 0 24rpx;
  padding: 100rpx 24rpx;
  background: #ffffff;

  .title {
    margin-bottom: 16rpx;
    color: #333333;
    font-size: 28rpx;
    font-weight: 700;
  }

  .desc {
    color: #666666;
    font-size: 24rpx;
    font-weight: 400;
  }

  .app-tags {
    .tag {
      padding: 12rpx 24rpx;
      border-radius: 28rpx;
      color: #666666;
      font-size: 24rpx;
      font-weight: 400;
      background: #f8f8f8;
    }
  }

  .player {
    padding: 8rpx 16rpx 8rpx 8rpx;
    width: 354rpx;
    height: 64rpx;
    border-radius: 40rpx;
    background: #f8f8f8;

    .icon-play {
      width: 48rpx;
      height: 48rpx;
    }

    .icon-sound {
      width: 172rpx;
      height: 32rpx;
    }

    .time {
      color: #666666;
      font-size: 24rpx;
      font-weight: 400;
    }
  }
}

.sbmit-btn {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 114rpx;
  margin: auto;
  border-radius: 50%;
  width: 152rpx;
  height: 152rpx;
  background: #666666;
  box-shadow: 0 0 32rpx 0 #bababa40;
  z-index: 1;

  &::after {
    border: none;
  }

  .inner {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    border-radius: 50%;
    width: 52rpx;
    height: 52rpx;
    background: #ffffff;
  }
}

.prompt-layer {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.4);
  z-index: 5;

  .prompt-popup {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 220rpx;
    // line-height: 200rpx;
    color: #000000;
    font-size: 28rpx;
    font-weight: 400;
    text-align: center;

    &::after {
      content: '';
      position: absolute;
      left: -10%;
      bottom: -52%;
      border-radius: 50%; //顶部圆弧，底部圆弧： 0 0 50% 50%
      width: 120%;
      height: 185%;
      background: #cccccc;
      z-index: -1;
    }
  }
}
</style>
